<?php

	fta_registerModules(
	 	array(
		"FTACart/FTACart"	
	 	)
	 );

	class FTAPayPalCart extends FTACart {
		
		var $pxaccess;
		var $currency;
		
		var $orderContainer;

		//var $addItemRequiredKeys;
		//store the order item here.. 
		var $lastKnownCartPhase;
		
		function __construct() {
			parent::__construct();			
			//..$this->currency = "NZD";
			global $db;	
			global $zdb;			
			
			$this->setCurrency(CART_CURRENCY);
		//	$this->addItemRequiredKeys = array("productId", "quantity");

		}
		
		
		
		function renderCart() {//was called render.. but cart is better
			global $db;
			global $CMS_ORDERCONTAINER_CLASS;
			

			
			///////////
			
			$valid = false; //validateMemberLogin($member,$db);
			
			//create order container.. if we dont have one.. 
			if (is_null($this->orderContainer)) {

				$this->orderContainer = new $CMS_ORDERCONTAINER_CLASS();
				
				//set the default country.. in the request for the take values for key stuff..
				$_REQUEST[ $this->orderContainer->keyForField('country')] = CART_DEFAULT_COUNTRY;
								
				// auto complete
				$this->orderContainer->takeValueForKey(false,'cartHasLogin');
						
				
			}
			////////// 
			// Pull the dps stuff out of the request.. 
			// $this->restoreOrderFromPaymentGateway();
						

			
			/*
			 populate the order container fields from the request the
			 the order container will in turn populate the fields of its
			 order items.
			*/
			$this->orderContainer->takeValuesFromRequest();
	
			
			# flush out items that are empty.. we dont want them confusing things..
			$this->orderContainer->purgeEmptyOrderItems();
	
			# invoke actions.. on the container..
			# no magical way of passing arguments.. 
			$deleteItemFromContainer = extractStringWithKeyFromArray('deleteItemFromContainer', $_REQUEST, null);
			if( !is_null($deleteItemFromContainer) && strlen($deleteItemFromContainer) == 8){
				$this->orderContainer->removeOrderItemWithId($deleteItemFromContainer);
				$returnUrl = extractStringWithKeyFromArray('returnUrl',$_REQUEST,null);
				if ($returnUrl){
					while (@ob_end_clean());					
					header("Location: " . $returnUrl ,true);
					die();
				}
			}
	
			# we insert a new order item at this point. when?? how.. 
			$createNewOrderItem = extractBooleanWithKeyFromArray(ORDER_CREATE_NEW_ITEM,$_REQUEST, true);
			$orderItem = null;
			
			/*
			 look for the current order item in the session.. this will set the current/active order item..
			 ie: the one we are currently looking at.. this only really has any use in 
			 wizard type setups where there are muliple steps involed in setting up
			 the order item and populating its fields.
			*/
			if (!$createNewOrderItem) {
				# $orderItem = null;//get the order out of the store
				$orderItemId = $this->orderContainer->valueForKey('currentOrderItemId');
				if (!is_null($orderItemId))
					$orderItem = $this->orderContainer->orderItemWithId( $orderItemId );
			}
		
			# determine the point in the order process that we are upto..
			$orderStep = extractStringWithKeyFromArray(ORDER_STEP_KEY, $_REQUEST, null);
			
			$this->orderContainer->purgeInvalidOrderItems();			
					
					
			// now the various render stages and what not...
			//;
			switch ($orderStep) {
					
					case ORDER_CANCEL:
						$this->cancelOrder();//dont want to include these seperate						
					break;
					
					case ORDER_FINALISE:
						$this->finaliseOrder();			
					break;

//					case ORDER_MANUAL_FINALISE:
//						$this->manualFinaliseOrder();
//					break;
					
					case ORDER_ITEM:
						$this->addItemToOrder();
					break;
									
					default:
						$this->displayOrder();						
					break;
						
					case ORDER_REVIEW:
						$this->reviewOrder();												
					break;
					
					case ORDER_SUBMIT:
						$this->submitOrder();
					break;
					
					// PayPal Order steps...
					case ORDER_PAYPAL_FINALISE:
						$this->paypalFinaliseOrder();			
					break;
					
					case ORDER_PAYPAL_REVIEW:				
						$this->paypalReviewAndSubmitOrder();
					break;

					case ORDER_PAYPAL_SUBMIT:
						$this->paypalSubmitOrder();
					break;
					
					case ORDER_PAYPAL_PDT:
						$this->paypalPDTRestoreOrderFromPaymentGateway();
					break;
					
					case ORDER_PAYPAL_IPN_LISTENER:
						$this->paypalInvokeIPNListener();
					break;
			}
	//		$_SESSION["FTACart"] = &$this;
						
		}

		function paypalPDTRestoreOrderFromPaymentGateway(){
			
			global $CMS_ORDERCONTAINER_CLASS;
			global $db;	 
			$authInfo = setupPublicUser();

			$this->orderContainer->log($this->orderContainer->id() . " PayPal - Checking for PayPal PDT Result.. .");
			
			// e.g. ?tx=2PB68492P99604941&st=Pending&amt=200.00&cc=USD&cm=&item_number=zdf73742
			// we don't really need other variables except tx and item_number
			// are we going to check amount we recorded and amount paid on paypal are same :/ ????
			$payPal_tx = extractStringWithKeyFromArray("tx", $_REQUEST, null);
			$payPal_st = extractStringWithKeyFromArray("st", $_REQUEST, null);
			// $payPal_item_number = extractStringWithKeyFromArray("custom", $_REQUEST, null);
			$payPal_item_number = extractStringWithKeyFromArray("cm", $_REQUEST, null);
			
			$payPalResponse = null;
			if (!is_null($payPal_tx) && !is_null($payPal_item_number) && !is_null($payPal_st)){
				
				// 
				$this->orderContainer->log($this->orderContainer->id() . " PayPal Found PayPal transaction ID: " . $payPal_tx);
				
				// this is the PayPal process.. 
				// we need to clean up the existing session here incase we try and update/edit the order..
				// these can cause problems..
				$_SESSION["_CMSKVC"] = null;				
				$this->orderContainer = null;

				$this->orderContainer = new $CMS_ORDERCONTAINER_CLASS();

				$originalContainerId = $payPal_item_number ? $payPal_item_number : null;
				
				$payPalResponse = $_GET; // mm don't how do we get just the PayPal data from the request, so doing this :/
				$this->orderContainer->log($this->orderContainer->id()." PayPal Order Id: $originalContainerId for PayPal PDT response in GET: " . print_r($payPalResponse,true));

				
				$this->orderContainer->log($originalContainerId." PayPal Return from PayPal.. Attempting to Load...");
				
				$this->orderContainer->log("order container id will be fangled from: " . $this->orderContainer->id()." to: " .$originalContainerId);	
				$res = $this->orderContainer->load($originalContainerId, $authInfo, $db);
				if ($res) {
										
					$this->orderContainer->log($this->orderContainer->id()." PayPal Return from PayPal.. Order with id: " . $originalContainerId ." restored");
					
					// since we are in an object, that should be happliy saved back to the session
					// we dont need to do this..
					//$_SESSION[ ORDER_CONTAINER_KEY ] = $this->orderContainer;
					$_SESSION["FTACart"] = &$this;					
					//HACK HACK HACK.. put these back into the request for the KVC to pull out
					$_REQUEST[ ORDER_CREATE_NEW_ITEM ] = false;	
					$_REQUEST[ ORDER_STEP_KEY ] = ORDER_PAYPAL_FINALISE;
					$this->paypalFinaliseOrder();
				} else {
					$this->orderContainer->log($originalContainerId." PayPal Return from PayPal.. failed to load order with id: " . $originalContainerId);					
					// while (@ob_end_clean());
					// header("Location: " . $this->getShopUrl(),true);
					// die();
				}
			} else {
				$this->orderContainer->log($this->orderContainer->id() . " PayPal No PayPal result in request, assume normal cart process");								
			}
		}
		
		/*
		* Does stuff done in reviewOrder function and then submit order if valid (just skipping review page)
		*/
		function paypalReviewAndSubmitOrder(){
			global $zdb;
			
			$this->orderContainer->log($this->orderContainer->id() . " PayPal - Performing order review process in the background : " );

			$this->lastKnownCartPhase = ORDER_PAYPAL_REVIEW;
						
			$this->orderContainer->takeValueForKey($this->getCurrency(),'currency');
			//we need to add a check here for the terms agree..
			
			// fucking hack here for the terms radio button..=	
			// radio buttons and checks are the most stupidly annoying thngs know to man.
			$termsAgreeKey = $this->orderContainer->keyForField('termsAgree');
			$termsAgree = extractBooleanWithKeyFromArray($termsAgreeKey, $_REQUEST, null);
			$this->orderContainer->takeValueForKey($termsAgree, 'termsAgree');
										
			$valid = false;
			$valid = $this->orderContainer->validateForSave();
			
		
			if(!$valid){
				$this->orderContainer->log($this->orderContainer->id() . " PayPal - Order not valid, returning to cart page:" );
				$_SESSION["FTACart"] = &$this;
				
				while (@ob_end_clean());
				header("Location: " . $this->getCartUrl(),true);
				die();
			} else {
				$this->orderContainer->log($this->orderContainer->id()." User on review page.");

				global $FTACartReviewPage;	// echo "FTACartReviewPage = $FTACartReviewPage";			
				include_once((0 < strlen($FTACartReviewPage)) ? $FTACartReviewPage : "ftaCartReview.php");			
			}					
		}
		
		
		function paypalSubmitOrder(){
			
			global $db;
			global $FTAPayPalDataArray;
			
			if (!is_array($FTAPayPalDataArray)){
				throw new Exception('$FTAPayPalDataArray is not configured');	
			}
			
			$authInfo = setupPublicUser();
			$ut = $authInfo->usertype;
			$authInfo->usertype = 0;
			$this->orderContainer->takeValueForKey( ORDER_STATUS_PAYPAL_PENDING, 'status');
			$res = $this->orderContainer->save( $authInfo, $db );
			$authInfo->usertype = $ut;
						
			// let's put the amount to charge to our pay pal data array
			if($this->orderContainer->valueForKey('totalPrice')){
				$FTAPayPalDataArray[PAYPAL_AMOUNT_VARIABLE] = $this->orderContainer->valueForKey('totalPrice');				
			} else {
				//TODO: if we have nothign to buy.. we should die.. - that rhymes :P
				// $FTAPayPalDataArray['amount'] = 0;
				while (@ob_end_clean());
				header("Location: " . $this->getShopUrl() ,true);
				die();
			}
			
			// get product name from the product module if $FTAPayPalDataArray['item_name'] has not been specified... :/
			$item_name = "";			
			if(!$FTAPayPalDataArray['item_name'] && is_array($this->orderContainer->orderItems()) && count($this->orderContainer->orderItems()) > 0){
				$count = 1;
				foreach ($this->orderContainer->orderItems() as $oi) {
					if($count == count($this->orderContainer->orderItems())){
						$suffix = "";
					} else {	
						$suffix = ", ";						
					}
					$item_name .= $oi->valueForKey('getProductName') . $suffix;
					$count++;
				}
				
			}
			
			$FTAPayPalDataArray[PAYPAL_ORDERID_VARIABLE] = $this->orderContainer->id();
							
			$this->lastKnownCartPhase = ORDER_PAYPAL_SUBMIT;
			
			$this->orderContainer->log($this->orderContainer->id() . " PayPal - Going to the PayPal for performing transaction, URL redirection to " . $this->getPayPalUrl() . " :" );
			while (@ob_end_clean());
			header("Location: " . $this->getPayPalUrl() ,true);
			die();
		}

		function paypalFinaliseOrder(){
			 
			$this->lastKnownCartPhase = ORDER_PAYPAL_FINALISE;

			$this->orderContainer->log($this->orderContainer->id() . " PayPal - Entering Order Finalise:");
			
			global $db;
			global $FTAPaymentStatusSuccess;
			global $FTAPaymentStatusPending;
			// global $FTAPaymentStatusFail;

			$FTAPaymentStatusSuccess = $this->getPayPalPayPalPaymentStatusSuccessArray();
			$FTAPaymentStatusPending = $this->getPayPalPayPalPaymentStatusPendingArray();
			/*
			 do the ecommerce bit..
			 record the order
			 and process ecommerce results??
			 now we may need to look up the session here.. to finalise things.. as this will also be triggered by
			 the dps..
			*/
						
			// PDT info from the REQUEST
			$payPal_tx = extractStringWithKeyFromArray("tx", $_REQUEST, null);
			// $payPal_item_number = extractStringWithKeyFromArray("custom", $_REQUEST, null);
			$payPal_item_number = extractStringWithKeyFromArray("cm", $_REQUEST, null);
			$payPal_st = extractStringWithKeyFromArray("st", $_REQUEST, null);
			// woop woop, didn't need to have this as a form, PayPal documentation is confusing :/
			// this is getting us response from PDT about the transaction
			$payPalPDTResponse = @file_get_contents(PAYPAL_PAYMENT_URL . "?cmd=_notify-synch&tx=" . $payPal_tx . "&at=" . PAYMENT_PDT_ID_TOKEN);
			
			
			//kvc operation?
			$status = $this->orderContainer->status();
			
			$sendInvoice=false;
			if ($status == ORDER_STATUS_PAYPAL_PENDING) {

				$this->orderContainer->log($this->orderContainer->id() . " PayPal PDT - Finalising Pending Order");
				
				$this->orderContainer->takeValueForKey( $payPal_st, 'responseText' );
		  		$this->orderContainer->takeValueForKey( $payPalPDTResponse, 'payPalReceive');
				$this->orderContainer->takeValueForKey( $payPal_tx, 'payPalTxId');
				
				// We'll still consider Pending status as a SUCCESSFUL transaction but on the finalise page we can say something like payment is still pending with PayPal for Review or whatever...
				// And have Status showing the email invoice...
				// IPN will handle things when PayPal accepts/declines the payment...

				// According to PayPal sandbox, possible payment statuses	:
				// - Canceled_Reversal, Denied, Expired, Failed
				// - Completed, Processed
				// - In-Progress, Pending
				// - Partially_Refunded, Refunded, Reversed, Voided
				// **Got this from Payment Status Glossary
				// - active, cleared, completed, paid, refunded
				// - held, in progress, on hold, on hold - ship now, pending, temporary hold, unclaimed, uncleared, under review
				// - canceled, denied, expired, failed, refused, returned, reversed
				if (in_array(strtolower($payPal_st), $FTAPaymentStatusSuccess) || in_array(strtolower($payPal_st), $FTAPaymentStatusPending))  {					
					$this->orderContainer->log($this->orderContainer->id() . " PayPal PDT - PayPal success.");
					if(in_array(strtolower($payPal_st), $FTAPaymentStatusSuccess)) {
						$this->orderContainer->log($this->orderContainer->id() . " PayPal PDT - PayPal Status set to: " . ORDER_STATUS_PAYPAL_SUCCESS);
						$this->orderContainer->takeValueForKey( ORDER_STATUS_PAYPAL_SUCCESS, 'status');
					} elseif(in_array(strtolower($payPal_st), $FTAPaymentStatusPending)) {
						$this->orderContainer->log($this->orderContainer->id() . " PayPal PDT - Status set to: " . ORDER_STATUS_PAYPAL_PENDING_PAYMENT_IN_PAYPAL);
						$this->orderContainer->takeValueForKey( ORDER_STATUS_PAYPAL_PENDING_PAYMENT_IN_PAYPAL, 'status');
					}
					
					$sendInvoice=true;
					
					$this->orderContainer->log($this->orderContainer->id() . " PayPal - Finalise Process will be ran when IPN kicks in...");
					
					// DO THIS IN IPN....
					// sending email invoice....					
					// global $FTACartFinaliseProcess;					
					// include_once((0 < strlen($FTACartFinaliseProcess)) ? $FTACartFinaliseProcess : "ftaCartFinaliseProcess.php");

					$this->lastKnownCartPhase = ORDER_PAYPAL_FINALISE_SUCCESS;

				} else {
					// In case there is no PDT response, we do this:
					if(!$payPalPDTResponse){
						$this->orderContainer->takeValueForKey( 'No PDT Response', 'payPalReceive' );						
						$this->orderContainer->log($this->orderContainer->id() . " PayPal - No PDT Response");					
					} else {
						$this->orderContainer->log($this->orderContainer->id() . " PayPal failed.");										
					}
					$this->orderContainer->takeValueForKey( ORDER_STATUS_PAYPAL_FAIL, 'status');					
					$this->lastKnownCartPhase = ORDER_PAYPAL_FINALISE_FAIL;
				}
										
				$authInfo = setupPublicUser();
				$ut = $authInfo->usertype;
				$authInfo->usertype = 0;
		  		$res = $this->orderContainer->save( $authInfo, $db );
				$authInfo->usertype = $ut;
											
											
			} else {
				$this->orderContainer->log($this->orderContainer->id() . " PayPal Order status already updated to: " . $status);				
				$this->orderContainer->takeValueForKey( $payPal_st, 'responseText' );
		  		$this->orderContainer->takeValueForKey( $payPalPDTResponse, 'payPalReceive');
				$this->orderContainer->takeValueForKey( $payPal_tx, 'payPalTxId');	
				
				$authInfo = setupPublicUser();
				$ut = $authInfo->usertype;
				$authInfo->usertype = 0;
		  		// include_once("site/lib/saveMember.php");
		  		$res = $this->orderContainer->save( $authInfo, $db );
				$authInfo->usertype = $ut;
			}
			
			$this->orderContainer->log($this->orderContainer->id() . " PayPal Displaying Finalise Page"); 
			if ($payPal_st == "Pending" || $payPal_st == "Completed")  {
				// We'll still consider Pending status as a SUCCESSFUL transaction but on the finalise page we can say something like payment is still pending with PayPal for Review or whatever...
				// And have Status showing in the email invoice...
				// IPN will handle things when PayPal accepts/declines the payment... 
				$this->lastKnownCartPhase = ORDER_PAYPAL_FINALISE_SUCCESS;							
			} else {
				$this->lastKnownCartPhase = ORDER_PAYPAL_FINALISE_FAIL;							
			}
			
			// TODO:
			// Need to mention status on this page...
			global $FTACartFinalisePage;						
			include_once((0 < strlen($FTACartFinalisePage)) ? $FTACartFinalisePage : "ftaCartFinalise.php");									
		}	
		
		function paypalInvokeIPNListener(){
			
//			xdebug_break( );
			
			global $db;
			global $CMS_ORDERCONTAINER_CLASS;
			global $FTAPaymentStatusSuccess;
			global $FTAPaymentStatusPending;
			// global $FTAPaymentStatusFail;
			
			$FTAPaymentStatusSuccess = $this->getPayPalPayPalPaymentStatusSuccessArray();
			$FTAPaymentStatusPending = $this->getPayPalPayPalPaymentStatusPendingArray();
			
			$this->lastKnownCartPhase = ORDER_PAYPAL_IPN_LISTENER;
			$this->orderContainer->log($this->orderContainer->id() . " PayPal IPN Listener - Received POST from IPN:  " . print_r($_REQUEST, true));
			
			// We need a default listener file in core FTACart...
			// TODO:
			// if status is VERIFIED, update the order status for the item_number (which is orderContainer Id)
			// - create new container, then resave the original one with updated status
			// - save the IPN response message 
			// - send email invoice
			if(isset($_POST) && $_POST){
				global $FTACartPayPalIPNListenerFile;
				include_once((0 < strlen($FTACartPayPalIPNListenerFile)) ? $FTACartPayPalIPNListenerFile : "ftaCartPayPalIPNListener.php");
				
				if ($verified){
					// TODO:
					// Check the payment_status is Completed
					// Check that txn_id has not been previously processed
					// Check that receiver_email is your Primary PayPal email
					// Check that payment_amount/payment_currency are correct
					// Process payment
					// If 'VERIFIED', send an email of IPN variables and values to the
					// specified email address
					
					// should we send an email to admin that order status is being updated?
					
					if(extractStringWithKeyFromArray(PAYPAL_ORDERID_VARIABLE, $_POST, NULL) && extractStringWithKeyFromArray('txn_id', $_POST, NULL) && extractStringWithKeyFromArray('receiver_email', $_POST, NULL) == PAYPAL_RECEIVER_EMAIL){
						$this->orderContainer->log($this->orderContainer->id() . " PayPal IPN Listener - Found PayPal transaction ID: " . extractStringWithKeyFromArray('txn_id', $_POST, NULL));
						
						//this is the dps process.. 
						// we need to clean up the existing session here incase we try and update/edit the order..
						//these can cause problems..
						$_SESSION["_CMSKVC"] = null;				
						$this->orderContainer = null;

						$this->orderContainer = new $CMS_ORDERCONTAINER_CLASS();

						$originalContainerId = extractStringWithKeyFromArray(PAYPAL_ORDERID_VARIABLE, $_POST, NULL);
						$this->orderContainer->log(print_r($originalContainerId, true));
						
						$payPalIPNMessage = ""; 
						foreach($_POST as $k => $v){
							$payPalIPNMessage .= $k . "=" . $v . "\n";
						}
						$payPalIPNResponse = $res; 	
						
						$this->orderContainer->log($this->orderContainer->id()." PayPal IPN Listener - Order Id: " . $originalContainerId . " for PayPal IPN response in POST: " . print_r($payPalIPNResponse,true));
						
						$this->orderContainer->log($originalContainerId . " PayPal IPN Listener - Attempting to Load Order ...");				
						$this->orderContainer->log(" PayPal IPN Listener - Order container id will be fangled from: " . $this->orderContainer->id()." to: " .$originalContainerId);	
						
						//TODO: Mention PayPal payment status in the Invoice

						$result = $this->orderContainer->load($originalContainerId, $authInfo, $db);
										
						if ($result) {
							$this->orderContainer->log($this->orderContainer->id() . " PayPal IPN Listener - Order with id: " . $originalContainerId ." restored");
							$this->orderContainer->log($this->orderContainer->id() . " PayPal IPN Listener - Checking txn_id, item_number matches the order's transaction id and order container id: ");

							if(extractStringWithKeyFromArray(PAYPAL_ORDERID_VARIABLE, $_POST, NULL) == $originalContainerId && extractStringWithKeyFromArray('mc_gross', $_POST, NULL) == number_format($this->orderContainer->valueForKey('totalPrice'), 2, '.', '') && extractStringWithKeyFromArray('mc_currency', $_POST, NULL) == $this->orderContainer->valueForKey('currency')){
								$this->orderContainer->log(" PayPal IPN Listener - Checking PayPal item_number(" . extractStringWithKeyFromArray(PAYPAL_ORDERID_VARIABLE, $_POST, NULL) . ") is same as Order container ID(" . $originalContainerId . ") ...");
								
								$this->orderContainer->log($this->orderContainer->id() . " PayPal IPN Listener - Updating order's responseText, ipnResponse: ");
								$this->orderContainer->takeValueForKey(extractStringWithKeyFromArray('payment_status', $_POST, NULL) . "(PayPal)", 'responseText' );
								$this->orderContainer->takeValueForKey($payPalIPNMessage, 'ipnMessage');
								$this->orderContainer->takeValueForKey($payPalIPNResponse, 'ipnResponse');		

								// According to PayPal sandbox, possible payment statuses	:
								// - Canceled_Reversal, Denied, Expired, Failed
								// - Completed, Processed
								// - In-Progress, Pending
								// - Partially_Refunded, Refunded, Reversed, Voided
								// **Got this from Payment Status Glossary
								// - active, cleared, completed, paid, refunded
								// - held, in progress, on hold, on hold - ship now, pending, temporary hold, unclaimed, uncleared, under review
								// - canceled, denied, expired, failed, refused, returned, reversed
								if(in_array(strtolower(extractStringWithKeyFromArray('payment_status', $_POST, NULL)), $FTAPaymentStatusSuccess)) {
									$this->orderContainer->log($this->orderContainer->id() . " PayPal IPN Listener - Order Status set to: " . ORDER_STATUS_PAYPAL_SUCCESS . "(SUCCESS)");
									$this->orderContainer->takeValueForKey( ORDER_STATUS_PAYPAL_SUCCESS, 'status');
								} elseif(in_array(strtolower(extractStringWithKeyFromArray('payment_status', $_POST, NULL)), $FTAPaymentStatusPending)) {
									$this->orderContainer->log($this->orderContainer->id() . " PayPal IPN Listener - Order Status set to: " . ORDER_STATUS_PAYPAL_PENDING_PAYMENT_IN_PAYPAL . "(PENDING)");
									$this->orderContainer->takeValueForKey( ORDER_STATUS_PAYPAL_PENDING_PAYMENT_IN_PAYPAL, 'status');
								} else {
									// rest all statuses will be treated as FAIL!
									$this->orderContainer->log($this->orderContainer->id() . " PayPal IPN Listener - Order Status set to: " . ORDER_STATUS_PAYPAL_FAIL . "(FAIL)");
									$this->orderContainer->takeValueForKey( ORDER_STATUS_PAYPAL_FAIL, 'status');
								}
								
								$authInfo = setupPublicUser();
								$ut = $authInfo->usertype;
								$authInfo->usertype = 0;
								$res = $this->orderContainer->save( $authInfo, $db );
								$authInfo->usertype = $ut;
								
								// send email invoice  with updated status, only if order was pending and changed to complete :/
								// mm may be send it anyway.. as one needs to be notified about the status, in case it was pending and got failed... :/
								if($this->orderContainer->status() == ORDER_STATUS_PAYPAL_SUCCESS){								
									$this->orderContainer->log($this->orderContainer->id() . " PayPal - Running finalise Process");
									global $FTACartFinaliseProcess;					
									include_once((0 < strlen($FTACartFinaliseProcess)) ? $FTACartFinaliseProcess : "ftaCartFinaliseProcess.php");
								}
								// do we need to do anything special here??
							}
						}
					}
				} else {
					// TODO: DIEEEE? what do we do :/
					if($invalidResponse){
						// We should save the IPN response regardless..
						$_SESSION["_CMSKVC"] = null;				
						$this->orderContainer = null;

						$this->orderContainer = new $CMS_ORDERCONTAINER_CLASS();

						$originalContainerId = extractStringWithKeyFromArray(PAYPAL_ORDERID_VARIABLE, $_POST, NULL);
						$this->orderContainer->log(print_r($originalContainerId, true));
					
						$payPalIPNMessage = ""; 
						foreach($_POST as $k => $v){
							$payPalIPNMessage .= $k . "=" . $v . "\n";
						}
						$payPalIPNResponse = $res; 
					
						$result = $this->orderContainer->load($originalContainerId, $authInfo, $db);
										
						if ($result) {
							$this->orderContainer->takeValueForKey(extractStringWithKeyFromArray('payment_status', $_POST, NULL) . "(PayPal)", 'responseText' );
							$this->orderContainer->takeValueForKey($payPalIPNMessage, 'ipnMessage');
							$this->orderContainer->takeValueForKey($payPalIPNResponse, 'ipnResponse');
							
							$this->orderContainer->takeValueForKey( ORDER_STATUS_PAYPAL_FAIL, 'status');
							
							$authInfo = setupPublicUser();
							$ut = $authInfo->usertype;
							$authInfo->usertype = 0;
							$res = $this->orderContainer->save( $authInfo, $db );
							$authInfo->usertype = $ut;
						}
					}
				}
			}			
		}
		
		// this is REQUIRED, can't rely on default stuff.....................
		function getPayPalDataArray() {
			global $FTAPayPalDataArray;
			return (0 < count($FTAPayPalDataArray)) ? $FTAPayPalDataArray : array("cmd"=>PAYPAL_BUTTON_TYPE,"amount"=>PAYPAL_AMOUNT,"currency_code"=>PAYPAL_CURRENCY);											
		}
		
		function getPayPalPayPalPaymentStatusSuccessArray() {
			global $FTAPaymentStatusSuccess;
			return (0 < count($FTAPaymentStatusSuccess)) ? $FTAPaymentStatusSuccess : array('active','cleared','completed','paid','refunded');											
		}
		
		function getPayPalPayPalPaymentStatusPendingArray() {
			global $FTAPaymentStatusPending;
			return (0 < count($FTAPaymentStatusPending)) ? $FTAPaymentStatusPending : array('held','in progress','on hold','on hold - ship now','pending','temporary hold','unclaimed','uncleared','under review');											
		}
		
		// don't really need this, but just in case... :/
		function getPayPalPayPalPaymentStatusFailArray() {
			global $FTAPaymentStatusFail;
			return (0 < count($FTAPaymentStatusFail)) ? $FTAPaymentStatusFail : array('canceled','denied','expired','failed','refused','returned','reversed');										
		}
				
		function getPayPalUrl() {
			global $FTAPayPalDataArray;
			
			if (!is_array($FTAPayPalDataArray)){
				throw new Exception('$FTAPayPalDataArray is not configured');	
			}
						
			$payPalPaymentUrl = PAYPAL_PAYMENT_URL;			
			// generating URL...
			$count = 0;
			foreach($FTAPayPalDataArray as $k => $v){
				if($count == 0){
					$payPalPaymentUrl .= '?' . $k . "=" . $v;
				} else {
					$payPalPaymentUrl .= '&' . $k . "=" . $v;
				}
				$count++;
			}		
	
			// return urlencode($payPalPaymentUrl);	
			return $payPalPaymentUrl;				
		}
	}
	
	// need a custom one for PayPal order statuses
	function payPalcartCleanup(){
		// we work out the last known step and clen up.. this should always be the last item to run in a cart page..
		// we dont dont this in the object.. as its bad.. and will get confusing..
		$ftaCart = &fta_getCartObject();
		if (ORDER_FINALISE_SUCCESS == $ftaCart->lastKnownCartPhase || ORDER_PAYPAL_FINALISE_SUCCESS == $ftaCart->lastKnownCartPhase || ORDER_PAYPAL_FINALISE_PENDING == $ftaCart->lastKnownCartPhase || ORDER_PAYPAL_FINALISE_FAIL == $ftaCart->lastKnownCartPhase) {
			//successful orders can goes here.. 
			// here we just remove all of the objects.. and hope that they go away..
			$ftaCart = null;
			unset($_SESSION['FTACart']);
			
			
			//
		} else if (ORDER_FINALISE_FAIL == $ftaCart->lastKnownCartPhase ) {
			//fail orders here.  // not sure if we need to clean up or not .. just leave for now.. 
		} else {
			//the rest of the states.. 	//nothing happens here.. 
		}
		
	}
